home *** CD-ROM | disk | FTP | other *** search
- #define ABOUT "usage: grep([flags],regular expression,input)\rgrep XFCN v3.1 by Greg Anderson 14 Sept 1989"
- /*
- | | grep XFCN:
- | |
- | | Greg Anderson
- | | 24 Kerr Hall
- | | Social Sciences Computing
- | | University of California, Santa Cruz
- | | sirkm@ssyx
- | |
- | | Given a search string and the contents of a card/background
- | | field, grep returns every line from the input field that
- | | contains the search string.
- | |
- | | Standard regular expressions are supported. See the file 'regexp.c'.
- | |
- | | Flags:
- | |
- | | -i : ignore case while searching
- | | -n : number each output line w/ its position in the input
- | | If the 'n' is followed immediately by a number (e.g. '-n3'),
- | | then each line number will be padded to that many
- | | characters. Padding is usually done with spaces, although
- | | zeros may be specified printf-style (i.e., '-n03').
- | | -c : display number of matches instead of output
- | | -v : inverted search: lines that DON'T match are returned
- | |
- | | Non-UNIX flags:
- | |
- | | -m : multiline match: indented lines are considered to be
- | | part of the preceeding line.
- | | -f : folded line match: lines that end with a backslash ("\")
- | | are considered to be continued on the next line.
- | |
- | | Example: Extracting a long, folded Cc: line from a mail message:
- | |
- | | put grep("-fi","^Cc:",theMail) into cc
- | |
- | | or: Removing all blank lines:
- | |
- | | put grep("-v","^$",foo) into foo
- | |
- | |
- |*/
-
- #include <MacTypes.h>
- #include <FileMgr.h>
- #include <SetUpA4.h>
- #include "HyperXCmd.h"
- #include "XCmdUtil.h"
- #include "regexp.h"
-
- /*-----------------------------------------------------------------
- | Global variables:
- -----------------------------------------------------------------*/
- char padchar;
- int spaces,
- grep_line,
- grep_matches;
-
- /*-----------------------------------------------------------------
- | Function types
- -----------------------------------------------------------------*/
- pascal void main();
- void grep();
- char searchline();
- char endsearch();
- char copyline();
- void copynumber();
- char advanceline();
-
- /*-----------------------------------------------------------------
- | This is the entry point to grep
- -----------------------------------------------------------------*/
- pascal void main (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- char *list;
- int i;
-
- /*
- | | Fix up LSC
- */
- RememberA0();
- SetUpA4();
- /*
- | | Check for the propper number of parameters
- */
- if( paramPtr->paramCount == 0 )
- {
- ReturnMsg(paramPtr,ABOUT);
- return;
- }
- if( (paramPtr->paramCount < 2) || (paramPtr->paramCount > 3) )
- {
- ReturnMsg(paramPtr,"Error in number of parameters.");
- return;
- }
- /*
- | | Move all parameters to top of heap and protect them
- */
- for (i=0;i<paramPtr->paramCount;i++)
- {
- MoveHHi(paramPtr->params[i]);
- HLock(paramPtr->params[i]);
- }
- /*
- | | Initialize global variables
- */
- padchar = ' ';
- spaces = 0;
- grep_line = 0;
- grep_matches = 0;
- regexp_flags = 0; /* From regexp.c */
- /*
- | | Search through flags, if any were specified
- */
- list = *(paramPtr->params[0]);
- if( (paramPtr->paramCount == 3) )
- {
- while( *list )
- {
- switch( *list++ )
- {
- case 'v': regexp_flags |= INVERT;
- break;
- case 'i': regexp_flags |= IGNORE;
- break;
- case 'n': regexp_flags |= NUMBER;
- while( (*list >= '0') && (*list <= '9') )
- {
- if( !spaces && (*list == '0') )
- padchar = '0';
- spaces = spaces * 10 + (*list - '0');
- ++list;
- }
- break;
- case 'c': regexp_flags |= COUNT;
- break;
- case 'm': regexp_flags |= MULTILINE;
- break;
- case 'f':
- case 'M': regexp_flags |= FOLDEDLINE;
- break;
- }
- }
- }
- /*
- | | Do the xcmd
- */
- grep(paramPtr);
- /*
- | | Unprotect the parameters so they can be freed by HyperCard
- */
- for (i=0;i<paramPtr->paramCount;i++)
- HUnlock(paramPtr->params[i]);
- /*
- | | The last thing to do before exiting:
- */
- RestoreA4();
- }
-
- /*-----------------------------------------------------------------
- | Search for the specified pattern
- -----------------------------------------------------------------*/
- void grep(paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Handle tempBuf;
- char *searchstring,
- *end,
- *str,
- *in,
- *out;
- int i,
- regexpparam,
- textparam,
- searchlen;
- long handLen;
-
- regexpparam = (paramPtr->paramCount == 3);
- textparam = regexpparam + 1;
- /*
- | |Create a temporary buffer the same size as the text buffer.
- */
- handLen = GetHandleSize(paramPtr->params[textparam]) + 100L;
- tempBuf = NewHandle((long)handLen);
- if( !tempBuf )
- {
- ReturnMsg(paramPtr,"Error allocating memory.");
- return;
- }
- MoveHHi(tempBuf);
- HLock(tempBuf);
-
- searchstring = *(paramPtr->params[regexpparam]);
- searchlen = greplen(&searchstring);
- in = *(paramPtr->params[textparam]);
- out = *tempBuf;
-
- if( searchlen < 0 )
- {
- DisposHandle(tempBuf);
- ReturnMsg(paramPtr,"Error in search string.");
- return;
- }
-
- while( searchline(searchstring,&in,&out) );
- /*
- | | If the COUNT flag is set, then overwrite the output
- | | with the number of matches
- */
- if( regexp_flags & COUNT )
- {
- out = *tempBuf;
- copynumber(grep_matches,&out);
- }
- *out = 0;
- paramPtr->returnValue = tempBuf;
- }
-
- /*-----------------------------------------------------------------
- | Check if the current line contains the search pattern
- -----------------------------------------------------------------*/
- char searchline(searchstring,in,out)
- char *searchstring,
- **in,
- **out;
- {
- char *start,
- *end,
- **start_p = &start,
- **end_p = &end;
- int found;
-
- /*
- | | If there is nothing on the last line, then it is not a line.
- */
- if( **in == 0 ) return(0);
-
- ++grep_line;
- if( regexp_flags & BEGINFLAG ) start_p = 0;
- if( regexp_flags & ENDFLAG ) end_p = 0;
-
- found = find_regexp(searchstring,*in,start_p,end_p);
-
- return( endsearch(in,out,found) );
- }
-
- /*-----------------------------------------------------------------
- | The search has ended: if match == 1, then the current line has
- | a match on it.
- -----------------------------------------------------------------*/
- char endsearch(in,out,match)
- char **in,
- **out;
- int match;
- {
- if( regexp_flags & INVERT )
- match = !match;
-
- if( match )
- {
- ++grep_matches;
- if( regexp_flags & NUMBER )
- {
- copynumber(grep_line,out);
- *(*out-1) = ':';
- *(*out)++ = ' ';
- }
- return( copyline(in,out) );
- }
- else
- return( advanceline(in) );
- }
-
- /*-----------------------------------------------------------------
- | The pattern was not found on this line; advance pointer
- -----------------------------------------------------------------*/
- char advanceline(fieldptr)
- char **fieldptr;
- {
- while( !end_of_line(*fieldptr) )
- (*fieldptr)++;
-
- return( *(*fieldptr)++ );
- }
-
- /*-----------------------------------------------------------------
- | If a pattern is found, copy the line to the output buffer
- -----------------------------------------------------------------*/
- char copyline(fieldptr,outputptr)
- char **fieldptr,
- **outputptr;
- {
- while( !end_of_line(*fieldptr) )
- {
- *(*outputptr)++ = *(*fieldptr)++;
- }
- *(*outputptr)++ = '\r';
- return( *(*fieldptr)++ );
- }
-
- /*-----------------------------------------------------------------
- | Pad spaces before a number, if necessary.
- -----------------------------------------------------------------*/
- padspaces(number,n_spaces,out)
- char **out;
- {
- int n = 10,
- m = 1;
-
- while( m < n_spaces )
- {
- if( (number < n) || (m > 4) )
- *(*out)++ = padchar;
- n *= 10;
- ++m;
- }
- }
-
- /*-----------------------------------------------------------------
- | Copy a number into the output buffer
- -----------------------------------------------------------------*/
- void copynumber(n,out)
- int n;
- char **out;
- {
- char temp[80],
- *ptr;
-
- padspaces(n,spaces,out);
-
- ptr = temp;
- itoa(ptr,n);
- copyline(&ptr,out);
- }
-
- /*-----------------------------------------------------------------
- | Count the number of characters on this line
- -----------------------------------------------------------------*/
- int lineLen(line)
- char *line;
- {
- int len = 0;
-
- while( !end_of_line(line) )
- {
- ++len;
- ++line;
- }
- return(len);
- }
-